﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace OrganizedConfusion
{
    public class StateManager : DrawableGameComponent
    {
        #region Fields
        List<GameState> states = new List<GameState>();
        List<GameState> statesToUpdate = new List<GameState>();

        SpriteBatch spriteBatch;
        SpriteFont font;
        bool isInitialized;
        Game OurGame;
        ContentManager content;

        public SpriteBatch Spritebatch
        { get { return spriteBatch; } }

        public SpriteFont Font
        { get { return font; } }
        #endregion

        #region Initialize
        public StateManager(Game game) : base(game) { OurGame = game; }

        public override void Initialize()
        {
            base.Initialize();
            isInitialized = true;
            content = Game.Content;
        }

        // Loads the graphic content for each state
        protected override void LoadContent()
        {
            content = Game.Content;
            spriteBatch = new SpriteBatch(GraphicsDevice);

            foreach (GameState state in states)
                state.LoadContent();

            font = content.Load<SpriteFont>("Fonts/Font");
        }

        // Unloads the graphic content for each state
        protected override void UnloadContent()
        {
            foreach(GameState state in states)
                state.UnloadContent();
        }
        #endregion

        #region update and draw
        /// <summary>
        /// Obsolete code
        /// </summary>
        /// <param name="gameTime"></param>
        public void OldUpdate(GameTime gameTime)
        {
            // Make sure the list is empty
            statesToUpdate.Clear();

            // Add master list of gamestates to the update list
            foreach (GameState state in states)
                statesToUpdate.Add(state);

            while (statesToUpdate.Count > 0)
            {
                GameState state = statesToUpdate[statesToUpdate.Count - 1];

                // remove the state you set
                statesToUpdate.RemoveAt(statesToUpdate.Count - 1);

                // update the state
                state.Update(gameTime);
            }
        }

        public override void Update(GameTime gameTime)
        {
            if(states.Count > 0)
                states[states.Count - 1].Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            foreach (GameState state in states)
            {
                state.Render(gameTime);
            }
        }
        #endregion

        #region Methods
        /// <summary>
        /// Called when you want to add a specific state, generally states that are overlayed.
        /// </summary>
        /// <param name="state"></param>
        public void AddState(GameState state)
        {
            state.Statemanager = this;

            // load after graphics device gets initialized
            if (isInitialized)
                state.LoadContent();

            states.Add(state);
        }

        /// <summary>
        /// Used for when you want to clear a specific state. ie A pause menu.
        /// </summary>
        /// <param name="state"></param>
        public void RemoveState(GameState state)
        {
            // unload if anything was loaded
                state.UnloadContent();

            states.Remove(state);
            statesToUpdate.Remove(state);
        }

        /// <summary>
        /// To get rid of all current states and add a fresh state.
        /// </summary>
        /// <param name="state"></param>
        public void Changestate(GameState state)
        {
            while (states.Count > 0)
            {
                GameState tempStates = states[states.Count - 1];
                RemoveState(tempStates);
            }
            AddState(state);
        }

        public GameState GetPrevState()
        {
            return states[states.Count - 2];
        }

        /// <summary>
        /// Called when you want to exit the game.
        /// </summary>
        public void EndGame()
        {
            while (states.Count > 0)
            {
                GameState tempStates = states[states.Count - 1];
                RemoveState(tempStates);
            }

            ContentsManager.Instance.ShutdownContentsManager();
            OurGame.Exit();
        }


        public StateManager GetThis()
        {
            return this;
        }
        #endregion
    }
}